<!DOCTYPE html>
<html lang="zh">

<head>
    <meta charset="UTF-8">
    <title>批量合成音频/识别字幕</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
        }

        body {
            padding: 20px;
            color: #333;
            font-size: 14px;
        }


        /* 遮罩层 */
        .overlay {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 1;
        }

        /* 弹窗样式 */
        .modal {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: #fff;
            padding: 20px;
            box-shadow:
                0px 4px 6px rgba(0, 0, 0, 0.1);
            z-index: 2;
            width: 300px;
            text-align: center;
        }

        /* 关闭按钮 */
        .close-btn {
            background-color: #f44336;
            color: white;
            border:
                none;
            padding: 5px 10px;
            cursor: pointer;
            border-radius: 5px;
        }

        .close-btn:hover {
            background-color: #d32f2f;
        }

        .description {
            line-height: 1.6;
            margin-bottom: 20px;
        }

        .actions {
            margin-bottom: 20px;
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .btn {
            padding: 6px 12px;
            border-radius: 4px;
            border: none;
            cursor: pointer;
        }

        .btn-primary {
            background: #1890ff;
            color: white;
        }

        .btn-default {
            background: #fff;
            border: 1px solid #d9d9d9;
        }

        .input-group {
            display: flex;
            align-items: center;
            margin-left: 10px;
        }

        .input-group input {
            width: 300px;
            padding: 4px 11px;
            border: 1px solid #d9d9d9;
            border-radius: 4px;
            margin-right: 10px;
        }

        .settings {
            margin: 20px 0;
            display: flex;
            align-items: center;
            gap: 20px;
        }

        .color-picker {
            background: #f0f0f0;
            padding: 2px 8px;
            border-radius: 2px;
            margin-left: 5px;
        }

        .speed-input {
            width: 60px;
            padding: 2px 6px;
            border: 1px solid #d9d9d9;
            border-radius: 2px;
        }

        .status {
            display: flex;
            align-items: center;
            gap: 10px;
            margin: 20px 0;
        }

        .status-btn {
            padding: 4px 15px;
            border-radius: 2px;
            border: 1px solid #d9d9d9;
            background: #fff;
            cursor: pointer;
        }

        .status-text {
            color: #ff4d4f;
        }

        table {
            width: 100%;
            border-collapse: collapse;
        }

        th,
        td {
            padding: 12px 8px;
            text-align: left;
            border-bottom: 1px solid #f0f0f0;
        }

        th {
            background: #fafafa;
            font-weight: 500;
        }

        .empty-state {
            text-align: center;
            padding: 40px 0;
            color: #999;
        }

        .empty-state img {
            width: 60px;
            height: 60px;
            margin-bottom: 10px;
            opacity: 0.3;
        }
    </style>
    <script src="qrc:///qtwebchannel/qwebchannel.js"></script>
</head>

<body>

    <div id="overlay" class="overlay" onclick="closeModal()"></div>

    <div id="modal" class="modal">
        <p id="message">消息弹窗</p>
        <!-- TODO: 调整消息弹窗样式 -->
        <button class="close-btn" onclick="closeModal()">关闭</button>
    </div>

    <div class="description">
        任务类型：<br>1. 文案-配音 2. 音视频 -> 字幕
        <br>
        <br>
        功能说明：
        <br>1. 导入文案：将文案文件导入到任务列表中，并自动生成配音文件。
        <br>2. 导入音/视频：将音/视频文件导入到任务列表中，并自动生成字幕文件。
        <br>3. 导出目录：选择导出目录，将任务列表中的文件导出到指定目录。
        <br>注意: 每次只能选择单一任务类型
    </div>

    <div class="actions">
        <button class="btn btn-primary" onclick="export_files('text')">导入文案</button>
        <button class="btn btn-primary" onclick="export_files('audio/video')">导入音/视频</button>
        <div class="input-group">
            <span>导出目录：</span>
            <input type="text" placeholder="请输入" id="export-dir" readonly onclick="chooseFolder('export-dir')" value="">
        </div>
    </div>

    <div class="settings">
        <h3>选择任务类型：</h3>
        <form id="radioForm">
            <div>
                <input type="radio" id="audio" name="radioGroup" value="audio">
                <label for="audio">配音</label>
            </div>
            <div>
                <input type="radio" id="subtitle" name="radioGroup" value="subtitle">
                <label for="subtitle">字幕</label>
            </div>
        </form>
        <div class="voice-color-select" style="display: none;">
            <label for="voiceColor">选择声音:</label>
            <select id="voiceColor">

            </select>
        </div>
    </div>
    <div class="status">
        <button class="status-btn" onclick="start_work()">开始任务</button>
        <button class="status-btn" onclick="stop_work()">终止任务</button>
    </div>

    <div>已选择<span id="checked-count">0</span>个文件(共<span id="upload-count">0</span>个文件)</div>

    <table>
        <thead>
            <tr>
                <th style="width: 40px;"><input type="checkbox" id="selectAll"></th>
                <th>序号</th>
                <th>文件名</th>
                <th>时长/秒</th>
                <th>大小</th>
                <th>状态</th>
            </tr>
        </thead>
        <tbody id="file-list">

        </tbody>
    </table>
    <script type="text/javascript">
        document.addEventListener("DOMContentLoaded", function () {
            let file_items = [];

            new QWebChannel(parent.qt.webChannelTransport, function (channel) {
                Bridge = channel.objects.Bridge;

                Bridge.result.connect(function (result) {
                    document.querySelector("tr[data-id='" + result + "']td[6]").textContent = "已完成";
                });

                Bridge.batch_ident_and_synthesis_result.connect(function (result) {
                    const tbody = document.getElementById('file-list');
                    if (!tbody) {
                        return;
                    }
                    let context_item = [];
                    for (let file_item of JSON.parse(result)) {
                        // 通过file_item的file来去重
                        let status = file_items.filter(item => item.file === file_item.file);
                        if (status.length === 0) {
                            let current_id = file_items.length + 1;

                            context_item.push(`
                                        <tr data-id="${current_id}">
                                            <td><label>
                                                <input type="checkbox" class="row-check" value="${file_item.file}">
                                            </label></td>
                                            <td>${current_id}</td>
                                            <td>${file_item.file}</td>
                                            <td>${file_item.duration}</td>
                                            <td>${file_item.size}</td>
                                            <td>${file_item.status || "未开始"}</td>
                                        </tr>
                                    `);
                            file_item["id"] = current_id;
                            file_item["status"] = "未开始";
                            file_item["selected"] = false;
                            file_items.push(file_item);
                        }
                    }
                    if (context_item.length > 0) {
                        tbody.innerHTML += context_item.join('');
                        document.getElementById("upload-count").innerText = file_items.length;
                        // 绑定每个行复选框：当所有被选中时自动勾选表头全选
                        document.querySelectorAll('.row-check').forEach(cb => {
                            cb.addEventListener('change', function (event) {
                                const all = document.querySelectorAll('.row-check');
                                const checked = document.querySelectorAll('.row-check:checked');
                                document.getElementById('checked-count').checked = all.length === checked.length;
                                document.getElementById('checked-count').innerText = checked.length;
                                if (cb.checked) {
                                    for (let item of file_items) {
                                        if (item.file === event.target.value) {
                                            item.selected = true;
                                        }
                                    }
                                }
                                else {
                                    for (let item of file_items) {
                                        if (item.file === event.target.value) {
                                            item.selected = false;
                                        }
                                    }
                                }
                            });
                        });
                    }
                });
                
                window.export_files = function (suffix) {
                    Bridge.batch_ident_and_synthesis(suffix);
                }
                // 选择的文件夹信号槽
                Bridge.select_folder_result.connect(function (eid, path) {
                    document.getElementById(eid).value = path;
                });

                window.chooseFolder = function (eid) {
                    Bridge.choose_folder(eid);
                };

                window.load_audio_metrail = function () {
                    Bridge.load_audio_model();
                };

                Bridge.load_audio_model_result.connect(function (content) {
                    let audio_models = JSON.parse(content);
                    let voiceColorSelect = document.getElementById("voiceColor");
                    if (!voiceColorSelect) {
                        return;
                    }
                    voiceColorSelect.innerHTML = audio_models.map(model => `
                                        <option value="${model.model};${model.voice}">${model.tone_name}</option>
                                    `).join('');
                });


                window.start_work = function () {
                    let work_channel = document.getElementById("radioForm").elements["radioGroup"].value;
                    let voice_color = document.getElementById("voiceColor").value;
                    let file_list = file_items.filter(item => item.selected);
                    let output_dir = document.getElementById("export-dir").value;
                    if (output_dir === "") {
                        showModal("请选择导出目录");
                        return;
                    }
                    if (file_list.length === 0) {
                        showModal("请先选择文件");
                        return;
                    }
                    Bridge.batch_synthesis_or_ident(JSON.stringify(
                        {
                            "files": file_list,
                            "channel": work_channel,
                            "voice": voice_color,
                            "output_dir": output_dir
                        }
                    ));
                };
                window.stop_work = function () {
                    Bridge.stop();
                };

                load_audio_metrail();

            });


            window.showModal = function (message) {
                document.getElementById("message").innerText = message;
                document.getElementById("overlay").style.display = "block";
                document.getElementById("modal").style.display = "block";
            };

            window.closeModal = function () {
                document.getElementById("overlay").style.display = "none";
                document.getElementById("modal").style.display = "none";
            };

            // 绑定全选框
            document.getElementById('selectAll').addEventListener('change', function () {
                const isChecked = this.checked;
                document.querySelectorAll('.row-check').forEach(cb => cb.checked = isChecked);
                document.getElementById('checked-count').innerText = isChecked ? file_items.length : 0;
                for (let item of file_items) {
                    item.selected = isChecked;
                }

            });
            // 监听单选框的变化
            document.getElementById('option1').addEventListener('change', () => {
                let voiceColorSelect = document.querySelector('.voice-color-select');
                if (option1.checked) {
                    voiceColorSelect.style.display = 'block'; // 显示下拉框
                } else {
                    voiceColorSelect.style.display = 'none'; // 隐藏下拉框
                }
            });


        });
    </script>

</body>

</html>